#include "common.h"
#include "regs.h"
#include "types.h"
#include "csr.h"
#include "print.h"

/*********************************************************************************************************
  寄存器偏移
*********************************************************************************************************/
#define PLIC_SIE_REG(x)      (PLIC_BASE + 0x2080 + 4 * ((x) / 32))
#define PLIC_SIE_POS(x)      (1 << ((x) % 32))
#define PLIC_SCLAIM_REG      (0x201004)
#define PLIC_STH_REG         (0x201000)
#define PLIC_CTRL_REG        (0x1FFFFC)

// 中断控制器初始化
void os_int_init(void)
{
    int i;

    // 清除 S 模式下所有中断
    csr_write(sip, 0);

    // 关闭控制器所有中断
    for (i = 0; i < 9; i++) {
        write32(0, PLIC_BASE + 0x2080 + 4 * i);
    }

    // 处理所有优先级中断
    for (i = 0; i < 256; i++) {
        write32(1, PLIC_BASE + 4 * i);
    }
    write32(0, PLIC_BASE + PLIC_STH_REG);
}

// 使能S模式下对plic寄存器的访问,此接口只能在M模式下调用
void rv_plic_smode_access_en(void)
{
    write32(1, PLIC_BASE + PLIC_CTRL_REG);
}

// 使能/禁止外设中断
void os_int_en(unsigned int vector, int en)
{
    u32 addr, val, old;
    addr = PLIC_SIE_REG(vector);
    val  = PLIC_SIE_POS(vector);
    old  = read32(addr);

    if (en) {
        write32(old | val, addr);
    } else {
        write32(old & ~val, addr);
    }
}

// 获取当前中断控制器外设中断号
unsigned int os_vector_get(void)
{
    // 清除 S 模式下外部控制器中断
    csr_clear(sip, 1 << 9);

    return  (read32(PLIC_BASE + PLIC_SCLAIM_REG));
}

// 中断处理完成
void os_int_done(unsigned int vector)
{
    write32(vector, PLIC_BASE + PLIC_SCLAIM_REG);
}